import vueGlobal from '../vueGlobal.js';
const pool = {};

function isEventExist(event) {
  return pool[event] && pool[event] instanceof Map;
}

function $on(event, handle, ctx) {
  if (typeof handle !== 'function') {
    throw new Error(`handle of listener ${event} is not a function`);
  }
  if (!isEventExist(event)) {
    pool[event] = new Map();
  }
  pool[event].set(handle, ctx);
  // console.log('pool after $on: ', event, pool);
}

function $off(event, handle) {
  if (!isEventExist(event)) {
    return console.log(`$off: listener ${event} is not exist`);
  }
  if (typeof handle === 'function') {
    pool[event].delete(handle);
  } else {
    pool[event].clear();
    delete pool[event];
  }
  // console.log('pool after $off: ', event, pool);
}

async function $emit(event, params) {
  params = Array.prototype.slice.call(arguments, 1);
  return await new Promise((resolve) => {
    if (!isEventExist(event)) {
      // console.log(`$emit: listener ${event} is not exist`);
      return resolve([]);
    }
    let results = [];
    pool[event].forEach((ctx, handle) => {
      results.push(handle.apply(ctx, params));
    });
    Promise.all(results).then((list) => {
      resolve(list.length > 1 ? list : list[0]);
    });
  });
}

export const vbus = { $on, $off, $emit };

vbus.install = function () {
  vueGlobal.set('$vbus', vbus);
  vueGlobal.set('$vBus', vbus);
};

export default vbus;
